﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Opennav.MapGenerator.Map.MapTiles;
using Opennav.MapGenerator.OSM;
using Opennav.MapGenerator.Map.Locations;
using Opennav.MapGenerator.Map.Roads;
using System.Text.RegularExpressions;
using Opennav.MapGenerator.Map.Labels;
using System.Diagnostics;
using System.IO;
using Opennav.MapGenerator.Map;
using Opennav.MapGenerator.Locator;
using Opennav.MapGenerator.Geometry;

namespace Opennav.MapGenerator
{
    class Program
    {
        static double Progress(long total, long current)
        {
            return ((double)current) * 100.0 / (double)total;
        }

        static void WriteUsage()
        {
            Console.WriteLine("Usage: mapgen <input> [options]");
            Console.WriteLine("Options:     -o <output>");
            Console.WriteLine("             -t <directory>");
            Console.WriteLine("             -l lvl0,lvl1,... ");
            Console.WriteLine("             -f \"some border name\"");
        }

        static void Main(string[] args)
        {
            if (args.Length % 2 == 1 && args.Length > 0) 
            {
                string tempFolder = null;
                string outputFile = null;
                string levels = null;
                string inputFile = args[0];
                string fakeBorder = null;
                for(int i = 1; i < args.Length; i++) 
                {
                    switch (args[i]) 
                    {
                        case "-o":
                            outputFile = args[++i];
                            break;
                        case "-t":
                            tempFolder = args[++i];
                            break;
                        case "-l":
                            levels = args[++i];
                            break;
                        case "-f":
                            fakeBorder = args[++i];
                            break;
                        default:
                            Console.WriteLine("unknown argument " + args[i] + "\n");
                            WriteUsage();
                            return;
                    }
                }
                if (!File.Exists(inputFile)) 
                {
                    Console.WriteLine("cannot find input file");
                    return;
                }
                if (tempFolder != null) 
                {
                    if (!Directory.Exists(tempFolder)) 
                    {
                        Console.WriteLine("cannot find temporary folder");
                        return;
                    }
                }
                if (outputFile == null) 
                {
                    outputFile = Path.Combine(Path.GetDirectoryName(inputFile), Path.GetFileNameWithoutExtension(inputFile) + ".output");
                }
                if (tempFolder == null) 
                {
                    tempFolder = Path.GetDirectoryName(outputFile);
                }
                List<Zoom> zoomLevels = new List<Zoom>();
                if (levels == null) 
                {
                    Console.WriteLine("using default zoom levels: 16,18,20,22");
                    zoomLevels.Add(new Zoom(0, 16));
                    zoomLevels.Add(new Zoom(1, 18));
                    zoomLevels.Add(new Zoom(2, 20));
                    zoomLevels.Add(new Zoom(3, 22));
                } 
                else 
                {
                    string[] l = levels.Split(',');
                    int lid = 0;
                    foreach (string level in l) 
                    {
                        try 
                        {
                            int resolution = Convert.ToInt32(level);
                            if (zoomLevels.Count > 0 && resolution <= zoomLevels.Last().Resolution) 
                            {
                                Console.WriteLine("wrong resolution order\n");
                                WriteUsage();
                                return;
                            }
                            zoomLevels.Add(new Zoom(lid++, resolution));
                        } 
                        catch (Exception e) 
                        {
                            Console.WriteLine("wrong format of levels\n");
                            WriteUsage();
                            return;
                        }
                    }
                }
                FileStream outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write);
                Console.WriteLine("loading osm data");
                BinCache src = BinCache.LoadFromXml(inputFile, tempFolder);
                Console.WriteLine("filling map");
                MapBuilder builder = new MapBuilder();
                MapFile map = new MapFile(zoomLevels);
                builder.FakeBorder = fakeBorder;
                builder.Build(map, src);
                Console.WriteLine("making map");
                map.Optimize();
                map.Preprocess();
                map.Generate(outputStream);
                src.Close();
                outputStream.Flush();
                outputStream.Close();
                Console.WriteLine("map generation complete");
                Console.ReadKey();
                return;
            }
            WriteUsage();
        }
    }
}
